package com.ysw.rpc.client.component;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.EventListener;
import com.alibaba.nacos.api.naming.pojo.Instance;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * @author YinShangwen
 * @since 2023/4/18 13:12
 */
@Slf4j
public class NacosComponent {
    private final NacosDiscoveryProperties nacosDiscoveryProperties;
    private final NacosServiceManager nacosServiceManager;

    public NacosComponent(NacosDiscoveryProperties nacosDiscoveryProperties, NacosServiceManager nacosServiceManager) {
        this.nacosDiscoveryProperties = nacosDiscoveryProperties;
        this.nacosServiceManager = nacosServiceManager;
    }

    /**
     * 获取所有服务
     *
     * @return 服务名列表
     */
    public List<String> getServices() {
        try {
            return namingService().getServicesOfServer(1, Integer.MAX_VALUE, getGroup()).getData();
        } catch (NacosException e) {
            if (log.isInfoEnabled()) {
                log.error("nacos error: not service", e);
            }
            return new ArrayList<>();
        }
    }

    /**
     * 获取一个健康的实例
     *
     * @param serviceName 服务名
     * @return instance
     */
    public Instance selectOneHealthyInstance(String serviceName) {
        try {
            return namingService().selectOneHealthyInstance(serviceName, getGroup(), false);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 订阅一个服务
     *
     * @param serviceName serviceName
     * @param listener    listener
     */
    public void subscribe(String serviceName, EventListener listener) {
        try {
            namingService().subscribe(serviceName, getGroup(), listener);
        } catch (NacosException e) {
            log.info("subscribe err code: {}, msg: {}", e.getErrCode(), e.getErrMsg());
        }
    }

    /**
     * 取消订阅一个服务
     *
     * @param serviceName serviceName
     */
    public void unsubscribe(String serviceName) {
        try {
            namingService().unsubscribe(serviceName, getGroup(), event -> {
            });
        } catch (NacosException e) {
            log.info("unsubscribe err code: {}, msg: {}", e.getErrCode(), e.getErrMsg());
        }
    }

    private String getGroup() {
        return nacosDiscoveryProperties.getGroup();
    }

    /**
     * 获取NamingService
     *
     * @return NamingService
     */
    public NamingService namingService() {
        return nacosServiceManager.getNamingService();
    }
}
